package model

import (
	"fmt"
	errMsg "ginblog/model/err"
	"ginblog/utils"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Username string `gorm:"type:varchar(20);not null" json:"username" validate:"required,min=4,max=12"`
	Password string `gorm:"type:varchar(20);not null" json:"password" validate:"required,min=6,max=20"`
	Role     int    `gorm:"type:int(11);default=2" json:"role" validate:"required,gte=2"`
	Avatar   string `gorm:"type:varchar(255)" json:"avatar"`
}

var UserNeedCheck = []string{"username"}

func (this *User) Check(p []string, m ...map[string]interface{}) errMsg.Code {
	var user User
	t := db.Table("user").Where("id != ?", this.ID)
	for _, item := range p {
		if len(m) > 0 {
			// 更新时，取map里需要校验的值
			t.Where(fmt.Sprintf("%v = ?", item), m[0][item])
		} else if v := utils.GetValueByFieldName(this, item); v != nil && fmt.Sprintf("%v", v) != "" {
			t.Where(fmt.Sprintf("%v = ?", item), v)
		}
	}
	tx := t.First(&user)
	if tx.Error != nil && tx.Error != gorm.ErrRecordNotFound {
		return errMsg.DB_ERROR
	}
	if user.ID > 0 {
		return errMsg.ERROR_USERNAME_USED
	}
	return errMsg.SUCCESS
}
func (this *User) BeforeSave(tx *gorm.DB) (err error) {
	this.Password, _ = utils.ScryptPwd(this.Password)
	return err
}

func (this *User) TableName() string {
	return "user"
}

func (this *User) EditUser(id int, data map[string]interface{}) errMsg.Code {
	tx := db.Model(this).Where("id = ?", id).Omit("password").Updates(data)
	if tx.Error != nil {
		return errMsg.DB_ERROR
	}
	if tx.RowsAffected == 0 {
		return errMsg.DB_OPTION_FAIL
	}
	return errMsg.SUCCESS
}

func (this *User) Delete() errMsg.Code {
	tx := db.Where("id=?", this.ID).Delete(&this)
	err := tx.Error
	if err != nil {
		return errMsg.DB_ERROR
	}
	if tx.RowsAffected == 0 {
		return errMsg.ERROR_USER_NOT_EXIST
	}
	return errMsg.SUCCESS
}

func (this *User) Create() errMsg.Code {
	//u.Password, _ = utils.ScryptPwd(u.Password)
	//op := db.Table("user").Create(this)
	tx := db.Create(this)
	if err := tx.Error; err != nil {
		return errMsg.DB_ERROR
	}
	if tx.RowsAffected == 0 {
		return errMsg.DB_OPTION_FAIL
	}
	return errMsg.SUCCESS
}

func FindUsers(pageSize, pageNum int, p ...map[string]interface{}) ([]User, errMsg.Code) {
	var (
		users []User
		err   error
	)
	err = db.Limit(pageSize).Offset((pageNum - 1) * pageSize).Order("updated_at desc").Find(&users).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, errMsg.DB_ERROR
	}
	return users, errMsg.SUCCESS
}

func CountUser(p map[string]interface{}) (int64, error) {
	var (
		count int64
	)
	tx := db.Table("user").Count(&count)
	return count, tx.Error
}

func Login(u *User) error {
	tx := db.Select([]string{"username", "password", "id"}).Where("username = ?", u.Username).First(u)
	return tx.Error
}
